In [ ]:
epochs = 10
n_test_batches = 200

भाग 11 - सुरक्षित गहन शिक्षण वर्गीकरण (Secure Deep Learning Classification)

आपका डेटा मायने रखता है, आपका मॉडल भी

डेटा मशीन लर्निंग के पीछे चालक है। डेटा बनाने और एकत्र करने वाले संगठन अपने स्वयं के मशीन लर्निंग मॉडल बनाने और प्रशिक्षित करने में सक्षम हैं। यह उन्हें बाहरी संगठनों के लिए एक सेवा (MLaaS) के रूप में ऐसे मॉडलों के उपयोग की पेशकश करने की अनुमति देता है। यह अन्य संगठनों के रूप में उपयोगी है जो शायद इन मॉडलों को स्वयं बनाने में सक्षम नहीं हैं, लेकिन जो अभी भी इस मॉडल का उपयोग अपने डेटा पर भविष्यवाणियां करने के लिए करना चाहते हैं।

हालाँकि, क्लाउड में होस्ट किया गया मॉडल अभी भी एक गोपनीयता / आईपी समस्या प्रस्तुत करता है। बाहरी संगठनों के लिए इसका उपयोग करने के लिए - उन्हें या तो अपना इनपुट डेटा (जैसे कि वर्गीकृत की जाने वाली छवियां) अपलोड करना होगा या मॉडल डाउनलोड करना होगा। इनपुट डेटा अपलोड करना गोपनीयता के दृष्टिकोण से समस्याग्रस्त हो सकता है, लेकिन मॉडल को डाउनलोड करना एक विकल्प नहीं हो सकता है यदि मॉडल बनाने / रखने वाले संगठन अपने आईपी को खोने के बारे में चिंतित हैं।

एन्क्रिप्टेड डेटा पर कम्प्यूटिंग

इस संदर्भ में, एक संभावित समाधान एक तरह से मॉडल और डेटा दोनों को एन्क्रिप्ट करना है, जो एक संगठन को किसी अन्य संगठन के स्वामित्व वाले मॉडल का उपयोग करने की अनुमति देता है, या तो अपने आईपी को एक दूसरे के सामने प्रकट किए बिना। कई एन्क्रिप्शन योजनाएं मौजूद हैं जो एन्क्रिप्ट किए गए डेटा पर गणना करने की अनुमति देती हैं, जिनमें से सिक्योर मल्टी-पार्टी कम्प्यूटेशन (एसएमएमसी), होमोमोर्फिक एन्क्रिप्शन (एफएचई / एसएचई) और फ़ंक्शनल एन्क्रिप्शन (एफई) सबसे अच्छे प्रकार हैं। हम यहां सुरक्षित बहु-पक्षीय संगणना (ट्यूटोरियल 5 में यहाँ विस्तार से प्रस्तुत किया गया है) पर ध्यान केंद्रित करेंगे। जिसमें निजी एडिटिव शेयरिंग हैं। यह SecureNN और SPDZ जैसे क्रिप्टो प्रोटोकॉल पर निर्भर करता है, जिसका विवरण इस उत्कृष्ट ब्लॉग पोस्ट में दिया गया है

ये प्रोटोकॉल एन्क्रिप्टेड डेटा पर उल्लेखनीय प्रदर्शन प्राप्त करते हैं, और पिछले कुछ महीनों से हम इन प्रोटोकॉल का उपयोग करना आसान बनाने के लिए काम कर रहे हैं। विशेष रूप से, हम आपको इन प्रोटोकॉल का उपयोग करने के लिए स्वयं प्रोटोकॉल को फिर से लागू किए बिना (या यहां तक कि यह कैसे काम करता है इसके पीछे की क्रिप्टोग्राफी जानना आवश्यक है) उपयोग करने के लिए उपकरण का निर्माण कर रहे हैं।

सेट अप

इस ट्यूटोरियल में सटीक सेटिंग निम्न है: विचार करें कि आप सर्वर हैं और आपके पास कुछ डेटा है। सबसे पहले, आप इस निजी प्रशिक्षण डेटा के साथ एक मॉडल को परिभाषित और प्रशिक्षित करते हैं। फिर, आप एक क्लाइंट के संपर्क में आते हैं जो अपना खुद का कुछ डेटा रखता है जो आपके मॉडल को कुछ पूर्वानुमान बनाने के लिए एक्सेस करना चाहते हैं।

आप अपने मॉडल (एक न्यूरल नेटवर्क) को एन्क्रिप्ट करते हैं। क्लाइंट उनके डेटा को एन्क्रिप्ट करता है। आप दोनों तब डेटा को वर्गीकृत करने के लिए मॉडल का उपयोग करने के लिए इन दो एन्क्रिप्टेड संपत्तियों का उपयोग करते हैं। अंत में, भविष्यवाणी का परिणाम ग्राहक को एक एन्क्रिप्टेड तरीके से वापस भेजा जाता है ताकि सर्वर (यानी आप) ग्राहक के डेटा के बारे में कुछ भी न सीखें (आप न तो इनपुट या भविष्यवाणी सीखते हैं)।

आदर्श रूप से हम additively client के इनपुट को स्वयं और सर्वर के बीच और मॉडल के लिए इसके विपरीत साझा करेंगे। सादगी के लिए, शेयरों को दो अन्य श्रमिकों alice और bob द्वारा आयोजित किया जाएगा। यदि आप समझते हैं कि एलिस का स्वामित्व क्लाइंट और सर्वर द्वारा बॉब के पास है, तो यह पूरी तरह से समतुल्य है।

गणना ईमानदार-लेकिन-जिज्ञासु प्रतिकूल मॉडल में सुरक्षित है जो कई एमपीसी फ्रेमवर्क में मानक है।

हमारे पास अब वह सब कुछ है जिसकी हमें आवश्यकता है, चलो शुरू करें!

लेखक:

अनुवादक:

चलिए शुरू करते हैं!

आयात और मॉडल विनिर्देशों


In [ ]:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms

हमें PySyft आयात करने / शुरू करने के लिए विशिष्ट कमांड निष्पादित करने की आवश्यकता है। हम कुछ (client,bob, और alice)नामित श्रमिकों का निर्माण करते हैं। अंत में, हम crypto_provider को परिभाषित करते हैं, जो सभी क्रिप्टो प्राइमेटिव्स देता है जिनकी हमें आवश्यकता हो सकती है, अधिक विवरण के लिए SMPC पर हमारे ट्यूटोरियल देखें)।


In [ ]:
import syft as sy
hook = sy.TorchHook(torch) 
client = sy.VirtualWorker(hook, id="client")
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
crypto_provider = sy.VirtualWorker(hook, id="crypto_provider")

हम सीखने के कार्य की सेटिंग को परिभाषित करते हैं


In [ ]:
class Arguments():
    def __init__(self):
        self.batch_size = 64
        self.test_batch_size = 50
        self.epochs = epochs
        self.lr = 0.001
        self.log_interval = 100

args = Arguments()

श्रमिकों को डेटा लोड करना और भेजना

हमारी प्रयोग में, हम मानते हैं कि सर्वर के पास पहले अपने मॉडल को प्रशिक्षित करने के लिए कुछ डेटा तक पहुंच है। यहाँ MNIST प्रशिक्षण सेट है।


In [ ]:
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=args.batch_size, shuffle=True)

दूसरा, क्लाइंट के पास कुछ डेटा है और वह सर्वर के मॉडल का उपयोग करके उस पर भविष्यवाणियां करना चाहेगा। यह ग्राहक अपने डेटा को दो श्रमिकों Alice औरBob में जोड़कर साझा करता है।

SMPC क्रिप्टो प्रोटोकॉल का उपयोग करता है जिसे पूर्णांक पर काम करने की आवश्यकता होती है। हम यहाँ PySyft टेंसर एब्स्ट्रैक्शन का लाभ उठाते हुए PyTorch Float टेंसर्स को .fix_precision()का उपयोग करके फिक्स्ड प्रिसिजन टेन्सर में परिवर्तित करते हैं। उदाहरण के लिए 0.123 सटीक 2 के साथ 2 दशमलव अंक पर पूर्णन है इसलिए संग्रहीत संख्या पूर्णांक 12 है।


In [ ]:
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('../data', train=False,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=args.test_batch_size, shuffle=True)

private_test_loader = []
for data, target in test_loader:
    private_test_loader.append((
        data.fix_precision().share(alice, bob, crypto_provider=crypto_provider),
        target.fix_precision().share(alice, bob, crypto_provider=crypto_provider)
    ))

फ़ीड फॉरवर्ड न्यूरल नेटवर्क विनिर्देश

इस नेटवर्क विनिर्देश का उपयोग सर्वर द्वारा किया जाता है


In [ ]:
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(784, 500)
        self.fc2 = nn.Linear(500, 10)

    def forward(self, x):
        x = x.view(-1, 784)
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        return x

प्रशिक्षण शुरू करें

प्रशिक्षण स्थानीय रूप से किया जाता है, इसलिए यह शुद्ध स्थानीय PyTorch प्रशिक्षण है, यहाँ कुछ खास नहीं है!


In [ ]:
def train(args, model, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        output = model(data)
        output = F.log_softmax(output, dim=1)
        loss = F.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if batch_idx % args.log_interval == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, batch_idx * args.batch_size, len(train_loader) * args.batch_size,
                100. * batch_idx / len(train_loader), loss.item()))

In [ ]:
model = Net()
optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)

for epoch in range(1, args.epochs + 1):
    train(args, model, train_loader, optimizer, epoch)

In [ ]:
def test(args, model, test_loader):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            output = model(data)
            output = F.log_softmax(output, dim=1)
            test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss
            pred = output.argmax(1, keepdim=True) # get the index of the max log-probability 
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)

    print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

In [ ]:
test(args, model, test_loader)

हमारा मॉडल अब प्रशिक्षित है और एक सेवा के रूप में प्रदान करने के लिए तैयार है!

सुरक्षित मूल्यांकन

अब, सर्वर के रूप में, हम डेटा रखने वाले श्रमिकों को मॉडल भेजते हैं। क्योंकि मॉडल संवेदनशील जानकारी है (आपने इसे अनुकूलित करने में समय बिताया है!), आप इसके भार का खुलासा नहीं करना चाहते हैं इसलिए आप उस मॉडल को गुप्त रूप से साझा करते हैं जैसे हमने डेटासेट के साथ किया था।


In [ ]:
model.fix_precision().share(alice, bob, crypto_provider=crypto_provider)

यह परीक्षण फ़ंक्शन एन्क्रिप्टेड मूल्यांकन करता है। मॉडल वज़न, डेटा इनपुट, भविष्यवाणी और स्कोरिंग के लिए उपयोग किए गए लक्ष्य एन्क्रिप्टेड हैं!

हालांकि, वाक्यविन्यास एक मॉडल के शुद्ध PyTorch परीक्षण के समान है, यह अच्छा नहीं है ?!

केवल एक चीज जिसे हम सर्वर की ओर से डिक्रिप्ट करते हैं, पूर्वानुमानों को सत्यापित करने के लिए अंत में अंतिम स्कोर औसत अच्छा था।


In [ ]:
def test(args, model, test_loader):
    model.eval()
    n_correct_priv = 0
    n_total = 0
    with torch.no_grad():
        for data, target in test_loader[:n_test_batches]:
            output = model(data)
            pred = output.argmax(dim=1) 
            n_correct_priv += pred.eq(target.view_as(pred)).sum()
            n_total += args.test_batch_size
# This 'test' function performs the encrypted evaluation. The model weights, the data inputs, the prediction and the target used for scoring are all encrypted!

# However as you can observe, the syntax is very similar to normal PyTorch testing! Nice!

# The only thing we decrypt from the server side is the final score at the end of our 200 items batches to verify predictions were on average good.      
            n_correct = n_correct_priv.copy().get().float_precision().long().item()
    
            print('Test set: Accuracy: {}/{} ({:.0f}%)'.format(
                n_correct, n_total,
                100. * n_correct / n_total))

In [ ]:
test(args, model, private_test_loader)

बधाई हो! यहां आप सीख चुके हैं कि एंड-टू-एंड सुरक्षित भविष्यवाणियां कैसे करें: सर्वर के मॉडल का वजन क्लाइंट के लिए लीक नहीं हुआ है और सर्वर को डेटा इनपुट के बारे में कोई जानकारी नहीं है और न ही वर्गीकरण आउटपुट!

प्रदर्शन के संबंध में, एक छवि को वर्गीकृत करने में 0.1 सेकंड से कम लगता है, लगभग 33ms मेरे लैपटॉप पर (2,7 गीगाहर्ट्ज इंटेल कोर i7, 16 जीबी रैम)। हालांकि, यह बहुत तेज़ संचार का उपयोग कर रहा है (सभी कार्यकर्ता मेरी स्थानीय मशीन पर हैं)। प्रदर्शन इस बात पर निर्भर करता है कि विभिन्न श्रमिक एक दूसरे से कितनी तेजी से बात कर सकते हैं।

निष्कर्ष

आपने देखा है कि एक क्रिप्टोकरंसी एक्सपर्ट होने के बिना, व्यावहारिक सुरक्षित मशीन लर्निंग प्रदर्शन करने और उपयोगकर्ताओं के डेटा की सुरक्षा करने के लिए PyTorch और PySyft का लाभ उठाना कितना आसान है!

इस विषय पर अधिक जल्द ही आ जाएगा, जिसमें अन्य पुस्तकालयों के संबंध में ठीक से बेंचमार्क PySyft प्रदर्शन, साथ ही तंत्रिका नेटवर्क के निजी एन्क्रिप्टेड प्रशिक्षण, जो की जरूरत है जब एक संगठन अपने स्वयं के मॉडल को प्रशिक्षित करने के लिए बाहरी संवेदनशील डेटा का समर्थन करता है। बने रहें!

यदि आपने इसका आनंद लिया और एआई और एआई आपूर्ति श्रृंखला (डेटा) के विकेन्द्रीकृत स्वामित्व के संरक्षण, गोपनीयता की ओर आंदोलन में शामिल होना चाहते हैं, तो आप निम्न तरीकों से ऐसा कर सकते हैं!

Pysyft को Github पर Star करें!

हमारे समुदाय की मदद करने का सबसे आसान तरीका सिर्फ रिपॉजिटरी को अभिनीत करना है! यह हमारे द्वारा बनाए जा रहे कूल टूल्स के बारे में जागरूकता बढ़ाने में मदद करता है।

GitHub पर हमारे ट्यूटोरियल उठाओ!

हमने फेडरेटेड और प्राइवेसी-प्रिजर्विंग लर्निंग की बेहतर समझ पाने के लिए वास्तव में अच्छा ट्यूटोरियल बनाया और ऐसा होने के लिए हम ईंटों का निर्माण कर रहे हैं।

हमारे Slack में शामिल हों!

नवीनतम प्रगति पर अद्यतित रहने का सबसे अच्छा तरीका हमारे समुदाय में शामिल होना है!

एक कोड परियोजना में शामिल हों!

हमारे समुदाय में योगदान करने का सबसे अच्छा तरीका एक कोड योगदानकर्ता बनना है! यदि आप "एक बंद" मिनी-प्रोजेक्ट्स शुरू करना चाहते हैं, तो आप PySyft GitHub जारी करने वाले पृष्ठ पर जा सकते हैं और 'अच्छा पहला अंक' चिह्नित मुद्दों की खोज कर सकते हैं।

दान करना

यदि आपके पास हमारे कोडबेस में योगदान करने का समय नहीं है, लेकिन फिर भी समर्थन उधार देना चाहते हैं, तो आप हमारे ओपन कलेक्टिव में भी एक बैकर बन सकते हैं। सभी दान हमारी वेब होस्टिंग और अन्य सामुदायिक खर्चों जैसे कि हैकाथॉन और मीटअप की ओर जाते हैं!


In [ ]: